import React, {Component} from 'react';
import {Modal, Toast} from 'antd-mobile';
import SocketEvent from '@/service/event';
import SocketUtils from '@/service/socket';
import Login from '@/pages/login';
import PlayerRandom from '@/pages/rooms/random';
import PlayerFreedom from '@/pages/rooms/freedom';
import BoardPlatform from '@/pages/board';
import styles from './index.less';
import config from '@/config';
import Platform, {MODE_FREEDOM_PK, MODE_RANDOM_PK, MODE_REVIEW, MODE_WATCH} from '@/pages/platform';
import {log} from '@/utils/log-utils';
import WatchPlatform from '@/pages/watch';
import ReviewPlatform from '@/pages/review';
import {btnSound, pauseAllSound, playSound, startAllSound} from "@/utils/sounds-res";
import {JOIN_ROOM_TYPE_FREEDOM, JOIN_ROOM_TYPE_RANDOM} from "@/utils/const-utils";
import AdvancedSpin from "@/spinner";

class Home extends Component {

  constructor(props) {
    super(props);

    /**
     * 页面枚举
     * @type {string}
     */
    this.login = 'login';
    this.platform = 'platform';
    this.playerRandom = 'playerRandom';
    this.playerFreedom = 'playerFreedom';
    this.board = 'board';
    this.watch = 'watch';
    this.review = 'review';

    /**
     * 角色枚举
     */
    this.roleBattle = 'ROLE_BATTLE';
    this.roleWatch = 'ROLE_WATCH';

    this.state = {
      text: '',
      loading: true,
      connectCount: 0,
      // 当前页面，(登录区)login，平台区platform，(匹配区)player，(游戏区)board (观战区)watch
      page: this.login,
      // 当前登录人信息
      userId: null,
      // 对战房间号
      roomId: null,
      // 对战编号
      battleId: null,
      // 加入房间的类型(自由匹配/随机匹配)
      joinRoomType: null,
      // 是否被踢出状态，此状态不需要断线重连等操作
      isKickOut: false,
    };

    SocketUtils.getSocket().then(socket => {
      this.socket = socket;

      // 启动服务监听，全局仅调用一次，会监听所有已注册的服务
      // 至于回调则由用户自己决定，提供 SocketEvent.register 进行回调注册
      // 并提供 SocketEvent.unRegister 卸载已注册的回调
      SocketEvent.startAllServiceLister(this.socket);
    })

    this.exceptionRespId = 'exceptionRespId';
    this.selfOfflineRespId = 'selfOfflineRespId';
    this.connectErrorId = 'connectErrorId';
    this.connectId = 'connectId';
    this.disconnectId = 'disconnectId';
    this.sessionRecoverRespId = 'sessionRecoverRespId';
    this.sessionRecoverNotifyId = 'sessionRecoverNotifyId';
    this.versionRespId = 'versionRespId';
    this.userConflictRespId = 'userConflictRespId';
  }

  componentDidMount() {
    // 启动监听
    this.startAllEventListen();
    // 页面显/隐的事件
    document.addEventListener('visibilitychange', (e) => {
      if (document.hidden) {
        pauseAllSound();
      } else {
        startAllSound();
      }
    });
  }

  /**
   * 组件绘制完成后开启socket连接结果监听
   */
  startAllEventListen = () => {
    SocketEvent.register('exceptionRespApi', this.exceptionRespId, resp => {
      log(`监听到全局异常, resp: `, resp);
      Modal.alert('系统错误', resp.msg, [
        {
          text: '确定', onPress: () => {
            playSound(btnSound);
          },
        },
      ]);
    })

    // 自动连接服务器失败后提供手动连接，若手动连接失败会回调此方法
    SocketEvent.register('connect_error', this.connectErrorId, () => {
      const { connectCount } = this.state;
      if (config.reconnection && connectCount < config.reconnectionAttempts) {
        this.setState({
          loading: true,
          connectCount: connectCount + 1,
          text: `连接服务器中(${connectCount + 1}/${config.reconnectionAttempts})`,
        });
      }
      // 判断重连是否超限
      if (!config.reconnection || connectCount === config.reconnectionAttempts) {
        this.setState({ loading: false });
        Modal.alert('系统提示', '服务器无响应', [
          {
            text: '重新连接', onPress: () => {
              playSound(btnSound);
              this.setState({ loading: true, text: '连接服务器中', connectCount: 0 });
              this.socket = this.socket.connect();
            },
          },
        ]);
      }
    });

    // 连接成功通知
    SocketEvent.register('connect', this.connectId, () => {
      this.setState({ loading: false });
    });

    // 断开连接通知
    SocketEvent.register('disconnect', this.disconnectId, () => {
      log(`服务器断开了连接`)
      // 如果是账号冲突则不进行重连了
      if (!this.state.isKickOut) {
        // 开了自动重连直接进行连接
        if (config.reconnection) {
          // 系统默认发起第一次重连
          this.setState({
            loading: true,
            text: `连接服务器中(1/${config.reconnectionAttempts})`,
            connectCount: 1,
          });
        } else {
          Modal.alert('系统提示', '与服务器断开连接', [
            {
              text: '重新连接', onPress: () => {
                playSound(btnSound);
                this.setState({loading: true, text: '连接服务器中', connectCount: 0});
                this.socket = this.socket.connect();
              },
            },
          ]);
        }
      } else {
        log(`被服务器踢出`)
      }
    });

    // 服务端主动返回需要恢复数据
    SocketEvent.register('sessionRecoverNotifyApi', this.sessionRecoverNotifyId, resp => {
      log(`会话恢复通知：`, resp);
      if (resp.code === 'success') {
        this.setState({ loading: true, text: resp.msg });
      }
    });

    // 会话恢复结果通知
    SocketEvent.register('sessionRecoverRespApi', this.sessionRecoverRespId, resp => {
      log(`会话恢复结果通知返回：`, resp);
      const { isKickOut, page: currPage, joinRoomType: currJoinRoomType } = this.state;
      const { role, roomId, roomUser, roomEnemy, page: serverPage, battleId, joinType: serverJoinRoomType = currJoinRoomType } = resp.data || {};

      // code: S000001, 仅通知消息
      // code: S000002, 房间和对局都未解散，开始恢复对局数据
      // code: S000003, 会话信息已经过期，刷新本页面
      // code: S000004, 对局已经结束，但该页面还可续相关事件

      if (resp.code === 'S000001') {
        Modal.alert('系统提示', resp.msg, [
          {
            text: '知道了', onPress: () => {
              playSound(btnSound);
            },
          }
        ]);
      } else if (resp.code === 'S000002') {
        // 用户的角色决定进什么模式（模式跟角色是同一套枚举）
        if (role === this.roleBattle) {
          this.setState({
            roomUser: roomUser,
            roomEnemy: roomEnemy,
            roomId: roomId,
            battleId: battleId,
            page: currPage !== this.board ? this.board : currPage,
            joinRoomType: serverJoinRoomType
          });
        } else if (role === this.roleWatch) {
          this.setState({
            roomId: roomId,
            battleId: battleId,
            page: currPage !== this.watch ? this.watch : currPage,
          });
        } else if(currPage !== serverPage) {
          this.setState({ page: serverPage, roomId: roomId, battleId: battleId, joinRoomType: serverJoinRoomType });
        }
      } else if (resp.code === 'S000003') {
        if(!isKickOut) {
          this.setState({ isKickOut: true, loading: false });
          Modal.alert('系统提示', '您的会话已经过期，请重新登录', [
            {
              text: '去登录', onPress: () => {
                playSound(btnSound);
                window.location.reload(true);
              },
            },
          ]);
        }
      }
      this.setState({ loading: false });
    });

    // 账号在其它地方登录提醒
    SocketEvent.register('userConflictRespApi', this.userConflictRespId, resp => {
      log(`账号登录冲突返回：`, resp);
      this.setState({ isKickOut: true, loading: false });
      Modal.alert('系统提示', '此账号在别处登录，您已被迫下线', [
        {
          text: '重新登录', onPress: () => {
            playSound(btnSound);
            window.location.reload(true);
          },
        },
      ]);
    });

    SocketEvent.register('versionRespApi', this.versionRespId, resp => {
      log(`游戏版本检测返回：`, resp);
      if (resp.code === 'success') {
        const { version } = resp.data;

        if (config.version !== version) {
          this.setState({ isKickOut: true, loading: false });
          Modal.alert('系统提示', `检测到客户端有新版本，请您更新!`, [
            {
              text: '重新加载', onPress: () => {
                playSound(btnSound);
                window.location.reload(true);
              },
            },
          ]);
        }
      }
    });
  };

  render() {
    const { page, joinRoomType } = this.state;
    return (
      <div className={styles.bg}>

        {/*登录模块*/}
        {
          page === this.login &&
          <Login
            socket={this.socket}
            loginSuccess={userId => {
              this.setState({ userId, page: this.platform });
            }}
          />
        }

        {/*游戏平台模块*/}
        {
          page === this.platform &&
          <Platform
            socket={this.socket}
            userId={this.state.userId}
            selectComplete={(mode) => {
              let page;
              let joinRoomType = null;
              switch (mode) {
                case MODE_WATCH:
                  page = this.watch;
                  break;
                case MODE_REVIEW:
                  page = this.review;
                  break;
                case MODE_RANDOM_PK:
                  page = this.playerRandom;
                  joinRoomType = JOIN_ROOM_TYPE_RANDOM;
                  break;
                case MODE_FREEDOM_PK:
                  page = this.playerFreedom
                  joinRoomType = JOIN_ROOM_TYPE_FREEDOM;
                  break;
                default:
                  Toast.show("模式选择错误");
                  page = this.platform;
                  break;
              }
              this.setState({ joinRoomType, page, roomId: null, battleId: null });
            }}
            goBack={() => this.setState({ page: this.login, roomId: null, battleId: null })}
          />
        }

        {/*匹配玩家(随机模式)*/}
        {
          page === this.playerRandom &&
          <PlayerRandom
            socket={this.socket}
            userId={this.state.userId}
            roomId={this.state.roomId}
            roomUser={this.state.roomUser}
            roomEnemy={this.state.roomEnemy}
            // 匹配成功
            matchSuccess={(battleId, roomId, roomUser, roomEnemy) => {
              this.setState({ page: this.board, battleId, roomId, roomUser, roomEnemy });
            }}
            // 离开匹配界面
            goBack={() => this.setState({ page: this.platform, roomId: null, battleId: null })}
          />
        }

        {/*匹配玩家(开房模式)*/}
        {
          page === this.playerFreedom &&
          <PlayerFreedom
            socket={this.socket}
            userId={this.state.userId}
            roomId={this.state.roomId}
            roomUser={this.state.roomUser}
            roomEnemy={this.state.roomEnemy}
            // 匹配成功
            matchSuccess={(battleId, roomId, roomUser, roomEnemy) => {
              this.setState({ page: this.board, battleId, roomId, roomUser, roomEnemy });
            }}
            // 离开匹配界面
            goBack={() => this.setState({ page: this.platform, roomId: null, battleId: null })}
          />
        }

        {/*对战棋盘模块*/}
        {
          page === this.board &&
          <BoardPlatform
            socket={this.socket}
            userId={this.state.userId}
            roomUser={this.state.roomUser}
            roomEnemy={this.state.roomEnemy}
            roomId={this.state.roomId}
            battleId={this.state.battleId}
            goPlatformView={() => this.setState({ page: this.platform, battleId: null, roomId: null})}
            goBack={() => this.setState({ page: joinRoomType === JOIN_ROOM_TYPE_FREEDOM ? this.playerFreedom : this.playerRandom, battleId: null })}
          />
        }

        {/*观战棋盘模块*/}
        {
          page === this.watch &&
          <WatchPlatform
            userId={this.state.userId}
            socket={this.socket}
            roomId={this.state.roomId}
            battleId={this.state.battleId}
            goBack={() => this.setState({ page: this.platform, roomId: null, battleId: null })}
          />
        }

        {/*对局复盘模块*/}
        {
          page === this.review &&
          <ReviewPlatform
            userId={this.state.userId}
            socket={this.socket}
            goBack={() => this.setState({ page: this.platform })}
          />
        }
        <AdvancedSpin text={this.state.text} show={this.state.loading}/>
      </div>
    );
  }
}

export default Home;
